package com.sprucetec.live.controller;

import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.metadata.Table;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.fastjson.JSON;
import com.sprucetec.live.annotation.GuavaTateLimeter;
import com.sprucetec.live.annotation.SystemControllerLog;
import com.sprucetec.live.base.entity.User;
import com.sprucetec.live.common.dto.PagedListDTO;
import com.sprucetec.live.common.dto.business.LiveChatDto;
import com.sprucetec.live.common.dto.business.LiveUserDto;
import com.sprucetec.live.common.dto.business.NettyMessageDto;
import com.sprucetec.live.common.util.DateFormatUtils;
import com.sprucetec.live.common.util.RespCode;
import com.sprucetec.live.common.util.ServiceResult;
import com.sprucetec.live.common.util.ServiceResultUtil;
import com.sprucetec.live.entity.LiveChat;
import com.sprucetec.live.entity.LiveVideo;
import com.sprucetec.live.enums.ChatTypeEnum;
import com.sprucetec.live.service.LiveChatService;
import com.sprucetec.live.util.SsoUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.WebAsyncTask;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author chenkai
 * @date 2020/4/2 4:33 下午
 * @description:
 */
@Slf4j
@RestController
@RequestMapping("/liveChat")
public class LiveChatController {

    @Autowired
    private LiveChatService liveChatService;

    /**
     * 获取聊天分页列表
     */
    @PostMapping("getLiveChatPage")
    public ServiceResult<PagedListDTO<LiveChatDto>> getLiveChatPage(@RequestBody LiveChatDto liveChatDto) {
        liveChatDto.judgePage();
        return ServiceResultUtil.success(liveChatService.getLiveChatPage(liveChatDto));
    }

    /**
     * 删除聊天信息
     */
    @SystemControllerLog(description = "删除聊天信息")
    @PostMapping("deleteChat")
    public ServiceResult<Integer> deleteChat(@RequestBody LiveChatDto liveChatDto) {

        return ServiceResultUtil.success(liveChatService.deleteChat(liveChatDto));
    }

    /**
     * 发布聊天/提问
     * 这里只是演示使用，因为mcq对发消息的功能做了削峰，这里因为没有那么大的并发，所以没有使用限流方案
     * 一秒钟只允许发100个消息
     *
     * @param liveChatDto
     * @return
     */
//    @RequestMapping("/addChat")
//    @GuavaTateLimeter(limit = 5000, timeOut = 1)
//    public WebAsyncTask<ServiceResult> addChat(@RequestBody LiveChatDto liveChatDto) {
//
//        User loginUser = SsoUtil.getLoginUser();
//        if (liveChatDto == null) {
//            return checkCallTask("参数错误");
//        }
//        String commentContent = liveChatDto.getContent();
//        Long videoId = liveChatDto.getVideoId();
//        Integer commentType = liveChatDto.getChatType();
//        if (videoId == null) {
//            return checkCallTask("参数错误：视频号不能为空");
//        }
//        if (StringUtils.isBlank(commentContent)) {
//            return checkCallTask("参数错误");
//        }
//        if (commentType == null) {
//            return checkCallTask("参数错误：type不能为空");
//        }
//        commentContent = commentContent.replaceAll("[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\u2600-\u27ff]", "*");
//        try {
//            liveChatDto.setContent(commentContent);
//            Callable<ServiceResult> callable = new Callable() {
//                @Override
//                public Object call() {
//                    //liveChat.video("美菜直播2020");
//                    liveChatDto.setCreateUserCode(loginUser.getUid());
//                    liveChatDto.setCreateUserName(loginUser.getName());
//                    liveChatDto.setCreateTime(new Date());
////                    liveChatDto.setUpdateTime(new Date());
////                    liveChatDto.setUpdateUserCode(loginUser.getUid());
////                    liveChatDto.setUpdateUserName(loginUser.getName());
//                    try {
//                        return liveChatService.addChat(liveChatDto);
//                    } catch (Exception e) {
//                        e.printStackTrace();
//                        log.error("发送消息失败,发送人{},错误为{}", liveChatDto.getCreateUserName(), e);
//                        return ServiceResultUtil.fail(RespCode.ERROR, "消息发送失败（可能操作频繁）");
//                    }
//                }
//            };
//            return new WebAsyncTask<>(callable);
//        } catch (Exception e) {
//            log.error("--发布评论-系统异常", e);
//            return checkCallTask("系统异常，请稍后重试");
//        }
//    }



    @RequestMapping("/addChat")
    @GuavaTateLimeter(limit = 5000, timeOut = 1)
    public WebAsyncTask<ServiceResult> addChat(@RequestBody LiveChatDto liveChatDto) {

       // User loginUser = SsoUtil.getLoginUser();
        if (liveChatDto == null) {
            return checkCallTask("参数错误");
        }
        String commentContent = liveChatDto.getContent();
        Long videoId = liveChatDto.getVideoId();
        Integer commentType = liveChatDto.getChatType();
        if (videoId == null) {
            return checkCallTask("参数错误：视频号不能为空");
        }
        if (StringUtils.isBlank(commentContent)) {
            return checkCallTask("参数错误");
        }
        if (commentType == null) {
            return checkCallTask("参数错误：type不能为空");
        }
        commentContent = commentContent.replaceAll("[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\u2600-\u27ff]", "*");
        try {
            liveChatDto.setContent(commentContent);
            Callable<ServiceResult> callable = new Callable() {
                @Override
                public Object call() {
                    //liveChat.video("美菜直播2020");
                    liveChatDto.setCreateUserCode(liveChatDto.getCreateUserCode());
                    liveChatDto.setCreateUserName(liveChatDto.getCreateUserName());
                    liveChatDto.setCreateTime(new Date());
//                    liveChatDto.setUpdateTime(new Date());
//                    liveChatDto.setUpdateUserCode(loginUser.getUid());
//                    liveChatDto.setUpdateUserName(loginUser.getName());
                    try {
                        return liveChatService.addChat(liveChatDto);
                    } catch (Exception e) {
                        e.printStackTrace();
                        log.error("发送消息失败,发送人{},错误为{}", liveChatDto.getCreateUserName(), e);
                        return ServiceResultUtil.fail(RespCode.ERROR, "消息发送失败（可能操作频繁）");
                    }
                }
            };
            return new WebAsyncTask<>(callable);
        } catch (Exception e) {
            log.error("--发布评论-系统异常", e);
            return checkCallTask("系统异常，请稍后重试");
        }
    }

    private WebAsyncTask checkCallTask(String message) {
        Callable<ServiceResult> callable = new Callable() {
            @Override
            public Object call() {
                ServiceResult serviceResult = new ServiceResult();
                serviceResult.setErrorCode(RespCode.ERROR.getCode());
                serviceResult.setMessage(message);
                return serviceResult;
            }
        };
        return new WebAsyncTask<>(callable);
    }


    /**
     * 获取评论列表
     *
     * @return
     */
    @RequestMapping("/getChatList")
    public WebAsyncTask<ServiceResult> getChatList(@RequestBody LiveChatDto liveChatDto) {
        log.info("start com getChatList method start with liveChatDto:{}", liveChatDto);
        Long videoId = liveChatDto.getVideoId();
        Integer chatType = liveChatDto.getChatType();
        if (videoId == null) {
            Callable<ServiceResult> callable = new Callable() {
                @Override
                public Object call() {
                    ServiceResult serviceResult = new ServiceResult();
                    serviceResult.setErrorCode(RespCode.ERROR.getCode());
                    serviceResult.setMessage("直播号不能为空");
                    return serviceResult;
                }
            };
            return new WebAsyncTask<>(callable);
        }
        if (chatType == null) {
            Callable<ServiceResult> callable = new Callable() {
                @Override
                public Object call() {
                    ServiceResult serviceResult = new ServiceResult();
                    serviceResult.setErrorCode(RespCode.ERROR.getCode());
                    serviceResult.setMessage("type不能为空");
                    return serviceResult;
                }
            };
            return new WebAsyncTask<>(callable);
        }
        Callable<ServiceResult> callable = new Callable() {
            @Override
            public Object call() throws InterruptedException {
                ServiceResult serviceResult = new ServiceResult();
                List<LiveChat> liveChats = liveChatService.getChatList(liveChatDto);
                serviceResult.setBody(liveChats);
                //更新redis相关数据统计信息(异步)
                serviceResult.setMessage("加载评论数据完成");
                serviceResult.setSuccess(true);
                return serviceResult;
            }
        };
        return new WebAsyncTask<>(callable);
    }

    /**
     * 获取Person界面的聊天评论列表
     */
    @RequestMapping("/getChatListOnPerson")
    public WebAsyncTask<ServiceResult> getChatListOnPerson(@RequestBody LiveChatDto liveChatDto) {
        log.info("start com getChatListOnPerson method start with liveChatDto:{}", liveChatDto);
        Callable<ServiceResult> callable = new Callable() {
            @Override
            public Object call() {
                ServiceResult serviceResult = new ServiceResult();
                serviceResult.setBody(liveChatService.getChatListOnPerson(liveChatDto));
                serviceResult.setMessage("加载评论数据完成");
                serviceResult.setSuccess(true);
                return serviceResult;
            }
        };
        return new WebAsyncTask<>(callable);
    }


    /**
     * 通过mq将消息转发到nettyServer 广播模式，解决websocket无法集群的方案
     */
    @PostMapping("socketSendByMq")
    public ServiceResult<Integer> socketSendByMq(@RequestBody NettyMessageDto liveChatDto) {
        return ServiceResultUtil.success(liveChatService.socketSendByMq(liveChatDto));
    }

    /**
     * 导出聊天/提问数据
     */
    @RequestMapping(value = "exportChatData", produces = "application/json; charset=utf-8")
    public ServiceResult<String> exportChatData(HttpServletResponse response, String obj) {
        LiveChatDto liveChatDto = new LiveChatDto();
        String fileName = "";

        try (ServletOutputStream out = response.getOutputStream()) {
            if (StringUtils.isNotEmpty(obj)) {
                liveChatDto = JSON.parseObject(obj, LiveChatDto.class);
            }
            String preStrng = liveChatDto.getChatType() == ChatTypeEnum.CHAT.getCode() ? "聊天" : "提问";
            fileName = liveChatDto.getTitle() + "_" + preStrng + "_" + DateFormatUtils.formatDate(new Date(), "yyyyMMddHHmmss");
            ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX);
            // 设置SHEET名称
            Sheet sheet = new Sheet(1, 0);
            sheet.setSheetName("sheet1");
            String[] headerArr = new String[]{"类型", "视频标题", "内容", "聊天人", "创建时间"};
            // 设置标题
            Table table = new Table(1);
            List<List<String>> titles = new ArrayList<>();
            for (String header : headerArr) {
                titles.add(Collections.singletonList(header));
            }
            table.setHead(titles);
            // 查数据写EXCEL
            List<List<String>> dataList = new ArrayList<>();
            List<LiveChatDto> liveChatDtos = liveChatService.exportChatData(liveChatDto);
            if (!CollectionUtils.isEmpty(liveChatDtos)) {
                LiveChatDto finalLiveChatDto = liveChatDto;
                liveChatDtos.forEach(chat -> dataList.add(Arrays.asList(
                        preStrng,
                        finalLiveChatDto.getTitle(),
                        chat.getContent(),
                        chat.getCreateUserName(),
                        DateFormatUtils.toStr("yyyy-MM-dd hh:mm:ss", chat.getCreateTime())
                        )
                ));
            }
            log.info("数据准备完成=====" + LocalDateTime.now().toString());
            writer.write0(dataList, sheet, table);
            // 下载EXCEL
            response.setHeader("Content-disposition", "attachment;filename=" + new String(fileName.getBytes("GBK"), "ISO8859_1") + ".xlsx");
            response.setContentType("multipart/form-data");
            response.setCharacterEncoding("utf-8");
            writer.finish();
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
            log.info(fileName, e);
            return ServiceResultUtil.fail(RespCode.ERROR, "IO异常");
        }
        log.info("导出文件完成=====" + LocalDateTime.now().toString());
        return ServiceResultUtil.success(fileName + "导出成功");
    }

}
